home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Graphics / sKulpt / skulpt-src / win-src / 2DWProc.cpp next >
Encoding:
C/C++ Source or Header  |  2000-06-28  |  49.8 KB  |  1,379 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16. #include <d3dx.h>
  17.  
  18. // Includes utilitaires D3D
  19. #include "d3dmath.h"
  20. #include "d3dutil.h"
  21. #include "D3DEnum.h"
  22.  
  23. // Ids Resources
  24. #include "resource.h"
  25.  
  26. // Constantes
  27. #include "const.h"
  28.  
  29. // Types
  30. #include "types.h"
  31.  
  32. // Variables globales projet
  33. #include "vars.h"
  34.  
  35. // Prototypes fonctions autres modules
  36. #include "proto.h"
  37.  
  38. // Macros
  39. #include "macros.h"
  40.  
  41. // Variables statiques au module
  42. static BOOL bTracking = FALSE;                            // Poursuite curseur en cours o/n (WM_LBUTTONDOWN / WM_MOUSEMOVE)
  43. static WPARAM wModifier;                                // Mémorisé sur le LBUTTONDOWN : SHIFT / CTRL / ...
  44. static HBRUSH hbrDkBlueSk, hbrLtBlueSk;                        // Brosses de remplissage
  45. static HPEN hpenWhite, hpenGrey, hpenCyan, hpenYellow, hpenPink, hpenDkBlueSk, hpenRed;    // Crayons
  46. static HFONT hFont;
  47.  
  48. // Forcer le redessin des 3 vues 2D (WM_PAINT)
  49. // Le paramètre sert à indiquer s'il faut tout redessiner (y/c triangles & sommets) -> TRUE
  50. // ou s'il ne faut redessiner que les curseurs, caméra & target
  51. void vForce2DRefresh(BOOL bMode)
  52. {
  53.     PostMessage(hWndTop,    WM_PAINT, 0, (LPARAM) bMode);
  54.     PostMessage(hWndFace,    WM_PAINT, 0, (LPARAM) bMode);
  55.     PostMessage(hWndRight,    WM_PAINT, 0, (LPARAM) bMode);
  56. }
  57.  
  58. // Callback management fenêtres vues 2D
  59. LRESULT CALLBACK lrPlanarWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  60. {
  61.     // Variables locales (Attention, réinitialiser à chaque fois : pas d'existence en dehors du traitement d'un message)
  62.     WinThings *pWT;                                        // Pointeur sur structure étendue fenêtre (double buffer, gadgets etc.)
  63.     PAINTSTRUCT hPStruct;                                // Pour WM_PAINT
  64.     HDC hdcWin= GetDC(hWnd);                                            // DC fenêtre
  65.     RECT rExtRect, rIntRect;                            // Zones client externe (avec gadgets) et interne (zone de dessin uniquement)                                    
  66.     HBRUSH hSaveBrush;                                    // Pour restaurer dans le HDC du double buffer
  67.     HPEN hSavePen;                                        // Pour restaurer dans le HDC du double buffer
  68.         
  69.     // Autres variables à usage général
  70.     register int iX, iY, iZ, iT, iWindowXMin, iWindowXMax, iWindowYMin, iWindowYMax;
  71.     float fXs, fYs, fZs, f3D2DXCoef, f3D2DYCoef;
  72.     HDC hdcDoubleBuf, hdcTripleBuf;
  73.     D3DVECTOR vVect1, vVect2;
  74.     POINT pClick;
  75.     COLORREF lColor;
  76.     char cCoords[80];
  77.     HMENU hMenu;
  78.     char cAxis;
  79.  
  80.     // Récupérer notre identifiant (vue dessus, face, droite) et mémoriser dans une globale pour que les autres fonctions sachent quelle fenêtre 2D est active
  81.     lWActive = GetWindowLong(hWnd, GWL_USERDATA);
  82.  
  83.     // Récupérer le rectangle complet de la zone client de la fenêtre
  84.     GetClientRect(hWnd, &rExtRect);
  85.  
  86.     // Cloner ce rectangle et le réduire pour laisser la place aux gadgets
  87.     CopyRect(&rIntRect, &rExtRect);
  88.     InflateRect(&rIntRect, -XDC_G_LARG, -XDC_G_HAUT);
  89.  
  90.     // Précalculer les coefficients de pente de conversion 3D/2D et déréférencer les coordonnées de la fenêtre
  91.     iWindowXMin = rIntRect.left; iWindowXMax = rIntRect.right;
  92.     iWindowYMax = rIntRect.top; iWindowYMin = rIntRect.bottom;
  93.     switch(lWActive)
  94.     {
  95.         case XDC_WID_TOP : // X et Z
  96.             f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fXmax - fXmin);
  97.             f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fZmax - fZmin);
  98.             break;
  99.  
  100.         case XDC_WID_FACE : // X et Y
  101.             f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fXmax - fXmin);
  102.             f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fYmax - fYmin);
  103.             break;
  104.                 
  105.         case XDC_WID_SIDE : // Z et Y
  106.             f3D2DXCoef = (float) (iWindowXMax - iWindowXMin) / (fZmax - fZmin);
  107.             f3D2DYCoef = (float) (iWindowYMax - iWindowYMin) / (fYmax - fYmin);
  108.             break;
  109.     }
  110.  
  111.     
  112.     // Récupérer le pointeur sur la structure de données étendue de la fenêtre (double & triple buffer, gadgets etc.)
  113.     pWT = (WinThings *) GetWindowLong(hWnd, 0);
  114.  
  115.     switch( uMsg )
  116.     {
  117.         case WM_CREATE:    //************************* C R E A T E ************************
  118.             // Allouer les objets GDI (globaux à toutes les fenêtres 2D d'où if ...)
  119.             if (!hpenWhite)        hpenWhite = CreatePen(PS_SOLID, 1, XDC_COL_WHITE);
  120.             if (!hpenRed)        hpenRed = CreatePen(PS_SOLID, 1, XDC_COL_RED);
  121.             if (!hpenYellow)    hpenYellow = CreatePen(PS_SOLID, 1, XDC_COL_YELLOW);
  122.             if (!hpenCyan)        hpenCyan = CreatePen(PS_SOLID, 1, XDC_COL_CYAN);
  123.             if (!hpenPink)        hpenPink = CreatePen(PS_SOLID, 1, XDC_COL_PINK);
  124.             if (!hpenGrey)        hpenGrey = CreatePen(PS_SOLID, 1, XDC_COL_GREY);
  125.             if (!hbrDkBlueSk)    hbrDkBlueSk = CreateSolidBrush(XDC_COL_DKBLUESK);
  126.             if (!hbrLtBlueSk)    hbrLtBlueSk = CreateSolidBrush(XDC_COL_LTBLUESK);
  127.             if (!hpenDkBlueSk)    hpenDkBlueSk = CreatePen(PS_SOLID, 1, XDC_COL_DKBLUESK);
  128.  
  129.             // Créer la fonte pour indiquer l'outil en cours à coté du curseur
  130.             if (!hFont)            hFont = CreateFont( -12,
  131.                                                     0, 0, 0, FW_BOLD, TRUE, FALSE, FALSE,
  132.                                                     ANSI_CHARSET,
  133.                                                     OUT_DEFAULT_PRECIS,
  134.                                                     CLIP_DEFAULT_PRECIS,
  135.                                                     DEFAULT_QUALITY,
  136.                                                     VARIABLE_PITCH,
  137.                                                     "Arial" );
  138.  
  139.             // Créer la structure de données étendue et l'attacher à la fenêtre
  140.             if (!(pWT = (WinThings *) malloc(sizeof(WinThings))))
  141.             {
  142.                 // Si fail, sortir de l'application
  143.                 PostQuitMessage(0);
  144.                 break;
  145.             }
  146.             SetWindowLong(hWnd, 0, (long) pWT);
  147.  
  148.             // Créer le double buffer et l'attacher à la structure de données étendue
  149.             pWT -> hdcDBuf = CreateCompatibleDC(hdcWin);
  150.             pWT -> hbDBuf = CreateCompatibleBitmap(hdcWin, rExtRect.right - rExtRect.left + 1, rExtRect.bottom - rExtRect.top  +1);
  151.             pWT -> holdDFont = (HFONT) SelectObject(pWT -> hdcDBuf, hFont);
  152.             pWT -> holdDBuf = SelectObject(pWT -> hdcDBuf, pWT -> hbDBuf);
  153.             SetBkMode(pWT -> hdcDBuf, TRANSPARENT);
  154.             SetTextColor(pWT -> hdcDBuf, XDC_COL_YELLOW);
  155.  
  156.             // Créer le triple buffer et l'attacher à la structure de données étendue
  157.             pWT -> hdcTBuf = CreateCompatibleDC(hdcWin);
  158.             pWT -> hbTBuf = CreateCompatibleBitmap(hdcWin, rExtRect.right - rExtRect.left + 1, rExtRect.bottom - rExtRect.top  +1);
  159.             pWT -> holdTBuf = SelectObject(pWT -> hdcTBuf, pWT -> hbTBuf);
  160.             pWT -> holdTBrush = (HBRUSH) SelectObject(pWT -> hdcTBuf, hbrLtBlueSk);
  161.             pWT -> holdTFont = (HFONT) SelectObject(pWT -> hdcTBuf, hFont);
  162.             SetBkMode(pWT -> hdcTBuf, TRANSPARENT);
  163.             SetTextColor(pWT -> hdcTBuf, XDC_COL_YELLOW);
  164.  
  165.             // Initialiser les pointeurs de gadgets sur l'imagerie gadgets (commune à toutes les fenêtres)
  166.             pWT -> Widgets[XDC_GID_AddPoint].Gad = &gAddPoint;
  167.             pWT -> Widgets[XDC_GID_Center].Gad = &gCenter;
  168.             pWT -> Widgets[XDC_GID_GoDown].Gad = &gGoDown;
  169.             pWT -> Widgets[XDC_GID_GoLeft].Gad = &gGoLeft;
  170.             pWT -> Widgets[XDC_GID_GoUp].Gad = &gGoUp;
  171.             pWT -> Widgets[XDC_GID_GoRight].Gad = &gGoRight;
  172.             pWT -> Widgets[XDC_GID_Grab].Gad = &gGrab;
  173.             pWT -> Widgets[XDC_GID_MakeTri].Gad = &gMakeTri;
  174.             pWT -> Widgets[XDC_GID_Reverse].Gad = &gReverse;
  175.             pWT -> Widgets[XDC_GID_RotAnti].Gad = &gRotAnti;
  176.             pWT -> Widgets[XDC_GID_RotClock].Gad = &gRotClock;
  177.             pWT -> Widgets[XDC_GID_ZoomIn].Gad = &gZoomIn;
  178.             pWT -> Widgets[XDC_GID_ZoomOut].Gad = &gZoomOut;
  179.  
  180.             // Se rappeler que le prochain WM_PAINT sera le premier
  181.             pWT -> bFirstPaint = TRUE;
  182.  
  183.             break;
  184.  
  185.         case WM_USER + 1: //*********************** Rafraichir le point d'indice wParam dans le double buffer
  186.                           // (-> refresh 2D mode partiel à suivre)
  187.             hdcDoubleBuf = pWT -> hdcDBuf;
  188.             vVect1 = Vertices[wParam].vPoint;
  189.  
  190.             switch(lWActive)
  191.             {
  192.                 case XDC_WID_TOP : // X et Z
  193.                     iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  194.                     iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef);
  195.                     break;
  196.  
  197.                 case XDC_WID_FACE : // X et Y
  198.                     iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  199.                     iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  200.                     break;
  201.                 
  202.                 case XDC_WID_SIDE : // Z et Y
  203.                     iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef);
  204.                     iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  205.                     break;
  206.             }
  207.  
  208.             // Tracer le sommet du triangle (petite croix)
  209.             lColor = Vertices[wParam].bSelected ? XDC_COL_YELLOW : XDC_COL_DKBLUESK;
  210.             SetPixel(hdcDoubleBuf, iX, iY, lColor);
  211.             SetPixel(hdcDoubleBuf, iX - 1, iY, lColor);
  212.             SetPixel(hdcDoubleBuf, iX + 1, iY, lColor);
  213.             SetPixel(hdcDoubleBuf, iX, iY - 1, lColor);
  214.             SetPixel(hdcDoubleBuf, iX, iY + 1, lColor);
  215.             break;
  216.  
  217.         case WM_PAINT: //************************** P A I N T ***********************
  218.             {
  219.                 // déréférencer les HDC du double et du triple buffer pour aller plus vite
  220.                 hdcDoubleBuf = pWT -> hdcDBuf;
  221.                 hdcTripleBuf = pWT -> hdcTBuf;
  222.  
  223.                 BeginPaint(hWnd, &hPStruct);
  224.  
  225.                 // On redessine tout seulement si on nous le demande ou si c'est le premier WM_PAINT
  226.                 if (((BOOL) lParam || pWT -> bFirstPaint) == XDC_MODE_PARTIEL) goto _skip;
  227.  
  228.                 // Se rappeller que les WM_PAINT à venir ne sont pas les premiers
  229.                 pWT -> bFirstPaint = FALSE;
  230.  
  231.                 // Remplir le grand rectangle en bleu foncé
  232.                 FillRect(hdcDoubleBuf, &rExtRect, hbrDkBlueSk);
  233.  
  234.                 // Remplir le petit rectangle en bleu clair avec tour blanc
  235.                 hSaveBrush = (HBRUSH) SelectObject(hdcDoubleBuf, hbrLtBlueSk);
  236.                 hSavePen = (HPEN) SelectObject(hdcDoubleBuf, hpenWhite);
  237.                 Rectangle(hdcDoubleBuf, iWindowXMin, iWindowYMin, iWindowXMax, iWindowYMax);
  238.  
  239.                 // Ajouter tous les gadgets Sculpt3D
  240.                 XDM_Bouton(pWT -> Widgets[XDC_GID_AddPoint], 0, 11);
  241.                 XDM_Bouton(pWT -> Widgets[XDC_GID_Center], XDC_G_LARG + 4, rExtRect.bottom - XDC_G_HAUT);
  242.                 XDM_Bouton(pWT -> Widgets[XDC_GID_GoDown], (rExtRect.right - rExtRect.left) / 2 - 8, rExtRect.bottom - XDC_G_HAUT);
  243.                 XDM_Bouton(pWT -> Widgets[XDC_GID_GoLeft], 0, (rExtRect.bottom - rExtRect.top) / 2 - 4);
  244.                 XDM_Bouton(pWT -> Widgets[XDC_GID_GoUp], (rExtRect.right - rExtRect.left) / 2 - 8, 0);
  245.                 XDM_Bouton(pWT -> Widgets[XDC_GID_GoRight], rExtRect.right - XDC_G_LARG, (rExtRect.bottom - rExtRect.top) / 2 - 4);
  246.                 XDM_Bouton(pWT -> Widgets[XDC_GID_Grab], 0, rExtRect.bottom - XDC_G_HAUT);
  247.                 XDM_Bouton(pWT -> Widgets[XDC_GID_MakeTri], 0, rExtRect.bottom - 20);
  248.                 XDM_Bouton(pWT -> Widgets[XDC_GID_Reverse], rExtRect.right - XDC_G_LARG, 16);
  249.                 XDM_Bouton(pWT -> Widgets[XDC_GID_RotAnti], 0, 0);
  250.                 XDM_Bouton(pWT -> Widgets[XDC_GID_RotClock], XDC_G_LARG + 2, 0);
  251.                 XDM_Bouton(pWT -> Widgets[XDC_GID_ZoomIn], rExtRect.right - 36, rExtRect.bottom - XDC_G_HAUT);
  252.                 XDM_Bouton(pWT -> Widgets[XDC_GID_ZoomOut], rExtRect.right - XDC_G_LARG, rExtRect.bottom - 20);
  253.  
  254.                 // Ecrire les noms des axes
  255.                 switch(lWActive)
  256.                 {
  257.                     case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut)
  258.                         cAxis = 'z'; ExtTextOut(hdcDoubleBuf, (rExtRect.right - rExtRect.left) / 2 + 12, -4, 0, NULL, &cAxis, 1, NULL);
  259.                         cAxis = 'x'; ExtTextOut(hdcDoubleBuf, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, NULL, &cAxis, 1, NULL);
  260.                         break;
  261.  
  262.                     case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut)
  263.                         cAxis = 'y'; ExtTextOut(hdcDoubleBuf, (rExtRect.right - rExtRect.left) / 2 + 12, -4, 0, NULL, &cAxis, 1, NULL);
  264.                         cAxis = 'x'; ExtTextOut(hdcDoubleBuf, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, NULL, &cAxis, 1, NULL);
  265.                         break;
  266.                     
  267.                     case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut)
  268.                         cAxis = 'y'; ExtTextOut(hdcDoubleBuf, (rExtRect.right - rExtRect.left) / 2 + 12, -4, 0, NULL, &cAxis, 1, NULL);
  269.                         cAxis = 'z'; ExtTextOut(hdcDoubleBuf, rExtRect.right - XDC_G_LARG + 5, (rExtRect.bottom - rExtRect.top) / 2 + 4, 0, NULL, &cAxis, 1, NULL);
  270.                         break;
  271.                 }
  272.  
  273.                 // Définir zone de clipping : rectangle interne
  274.                 IntersectClipRect(hdcDoubleBuf,iWindowXMin + 1, iWindowYMax + 1, iWindowXMax - 1, iWindowYMin - 1);
  275.  
  276.                 // Tracer la grille (si elle est activée)
  277.                 if (bGrid)
  278.                 {
  279.                     switch(lWActive)
  280.                     {
  281.                     case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut)
  282.                         for (fXs = XDM_toGrid(fXmin) ; fXs <= XDM_toGrid(fXmax) ; fXs += fGridSize)
  283.                             for (fZs = XDM_toGrid(fZmin) ; fZs <= XDM_toGrid(fZmax) ; fZs += fGridSize)
  284.                                 SetPixel(hdcDoubleBuf,
  285.                                          XDM_to2D(fXs, fXmin, iWindowXMin, f3D2DXCoef),
  286.                                          XDM_to2D(fZs, fZmin, iWindowYMin, f3D2DYCoef),
  287.                                          XDC_COL_GRID);
  288.                         break;
  289.  
  290.                     case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut)
  291.                         for (fXs = XDM_toGrid(fXmin) ; fXs <= XDM_toGrid(fXmax) ; fXs += fGridSize)
  292.                             for (fYs = XDM_toGrid(fYmin) ; fYs <= XDM_toGrid(fYmax) ; fYs += fGridSize)
  293.                                 SetPixel(hdcDoubleBuf,
  294.                                          XDM_to2D(fXs, fXmin, iWindowXMin, f3D2DXCoef),
  295.                                          XDM_to2D(fYs, fYmin, iWindowYMin, f3D2DYCoef),
  296.                                          XDC_COL_GRID);
  297.                         break;
  298.                     
  299.                     case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut)
  300.                         for (fZs = XDM_toGrid(fZmin) ; fZs <= XDM_toGrid(fZmax) ; fZs += fGridSize)
  301.                             for (fYs = XDM_toGrid(fYmin) ; fYs <= XDM_toGrid(fYmax) ; fYs += fGridSize)
  302.                                 SetPixel(hdcDoubleBuf,
  303.                                          XDM_to2D(fZs, fZmin, iWindowXMin, f3D2DXCoef),
  304.                                          XDM_to2D(fYs, fYmin, iWindowYMin, f3D2DYCoef),
  305.                                          XDC_COL_GRID);
  306.                         break;
  307.                     }
  308.                 }
  309.  
  310.                 // Tracer les axes du repère, en gris
  311.                 SelectObject(hdcDoubleBuf, hpenGrey);
  312.                 switch(lWActive)
  313.                 {
  314.                 case XDC_WID_TOP : // Axes X (gauche > droite) et Z (bas > haut)
  315.                     iY = (int) XDM_to2D(0, fZmin, iWindowYMin, f3D2DYCoef);
  316.                     MoveToEx(hdcDoubleBuf, iWindowXMax, iY, NULL); LineTo(hdcDoubleBuf, iWindowXMin, iY);
  317.  
  318.                     iX = (int) XDM_to2D(0, fXmin, iWindowXMin, f3D2DXCoef);
  319.                     MoveToEx(hdcDoubleBuf, iX, iWindowYMin, NULL); LineTo(hdcDoubleBuf, iX, iWindowYMax);
  320.                     break;
  321.  
  322.                 case XDC_WID_FACE : // Axes X (gauche > droite) et Y (bas > haut)
  323.                     iY = (int) XDM_to2D(0, fYmin, iWindowYMin, f3D2DYCoef);
  324.                     MoveToEx(hdcDoubleBuf, iWindowXMax, iY, NULL); LineTo(hdcDoubleBuf, iWindowXMin, iY);
  325.                     
  326.                     iX = (int) XDM_to2D(0, fXmin, iWindowXMin, f3D2DXCoef);
  327.                     MoveToEx(hdcDoubleBuf, iX, iWindowYMin, NULL); LineTo(hdcDoubleBuf, iX, iWindowYMax);
  328.                     break;
  329.                 
  330.                 case XDC_WID_SIDE : // Axes Z (gauche > droite) et Y (bas > haut)
  331.                     iY = (int) XDM_to2D(0, fYmin, iWindowYMin, f3D2DYCoef);
  332.                     MoveToEx(hdcDoubleBuf, iWindowXMax, iY, NULL); LineTo(hdcDoubleBuf, iWindowXMin, iY);
  333.                     
  334.                     iX = (int) XDM_to2D(0, fZmin, iWindowXMin, f3D2DXCoef);
  335.                     MoveToEx(hdcDoubleBuf, iX, iWindowYMin, NULL); LineTo(hdcDoubleBuf, iX, iWindowYMax);
  336.                     break;
  337.                 }
  338.  
  339.                 // Tracer les objets géométriques
  340.  
  341.                 // 1 - Arêtes
  342.                 // Choisir le crayon rouge
  343.                 {
  344.                     SelectObject(hdcDoubleBuf, hpenRed);
  345.                     for (int iEdge = 0 ; iEdge <= iEdgeLastUsed ; iEdge++)
  346.                     {
  347.                         // Ignorer les arêtes inexistants
  348.                         if (Edges[iEdge].bEnabled == FALSE) continue;
  349.  
  350.                         // Ignorer les arêtes cachés
  351.                         if (Edges[iEdge].bHidden == TRUE) continue;
  352.  
  353.                         vVect1 = Vertices[Edges[iEdge].iSommets[0]].vPoint;
  354.                         vVect2 = Vertices[Edges[iEdge].iSommets[1]].vPoint;
  355.                         
  356.                         switch(lWActive)
  357.                         {
  358.                             case XDC_WID_TOP : // X et Z
  359.                                 iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  360.                                 iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef);
  361.                                 iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef);
  362.                                 iT = (int) XDM_to2D(vVect2.z, fZmin, iWindowYMin, f3D2DYCoef);
  363.                                 break;
  364.  
  365.                             case XDC_WID_FACE : // X et Y
  366.                                 iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  367.                                 iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  368.                                 iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef);
  369.                                 iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef);
  370.                                 break;
  371.                             
  372.                             case XDC_WID_SIDE : // Z et Y
  373.                                 iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef);
  374.                                 iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  375.                                 iZ = (int) XDM_to2D(vVect2.z, fZmin, iWindowXMin, f3D2DXCoef);
  376.                                 iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef);
  377.                                 break;
  378.                         }
  379.  
  380.                         // Tracer l'arête
  381.                         MoveToEx(hdcDoubleBuf, iX, iY, NULL); LineTo(hdcDoubleBuf, iZ, iT);
  382.                     }
  383.  
  384.                     // 2 - Triangles
  385.                     // Choisir le crayon rose
  386.                     SelectObject(hdcDoubleBuf, hpenPink);
  387.                     for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  388.                     {
  389.                         // Ignorer les triangles inexistants
  390.                         if (Triangles[iTriangle].bEnabled == FALSE) continue;
  391.  
  392.                         // Ignorer les triangles cachés
  393.                         if (Triangles[iTriangle].bHidden == TRUE) continue;
  394.                         
  395.                         // Pour chaque coté du triangle (on ne trace que les 3 premiers, les 3 suivants étant les mêmes dans un ordre différent)
  396.                         for (int iSommet = 0 ; iSommet < 3 ; iSommet++)
  397.                         {
  398.                             // Déterminer les coordonnées de la projection du segment (sommet, sommet suivant) sur la fenêtre en cours
  399.                             // --> segment (iX, iY) - (iZ, iT)
  400.                             int iSommetSuivant = (iSommet + 1) % 3;
  401.  
  402.                             vVect1 = Vertices[Triangles[iTriangle].iSommets[iSommet]].vPoint;
  403.                             vVect2 = Vertices[Triangles[iTriangle].iSommets[iSommetSuivant]].vPoint;
  404.  
  405.                             switch(lWActive)
  406.                             {
  407.                                 case XDC_WID_TOP : // X et Z
  408.                                     iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  409.                                     iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef);
  410.                                     iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef);
  411.                                     iT = (int) XDM_to2D(vVect2.z, fZmin, iWindowYMin, f3D2DYCoef);
  412.                                     break;
  413.  
  414.                                 case XDC_WID_FACE : // X et Y
  415.                                     iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  416.                                     iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  417.                                     iZ = (int) XDM_to2D(vVect2.x, fXmin, iWindowXMin, f3D2DXCoef);
  418.                                     iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef);
  419.                                     break;
  420.                                 
  421.                                 case XDC_WID_SIDE : // Z et Y
  422.                                     iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef);
  423.                                     iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  424.                                     iZ = (int) XDM_to2D(vVect2.z, fZmin, iWindowXMin, f3D2DXCoef);
  425.                                     iT = (int) XDM_to2D(vVect2.y, fYmin, iWindowYMin, f3D2DYCoef);
  426.                                     break;
  427.                             }
  428.  
  429.                             // Tracer l'arête du triangle
  430.                             MoveToEx(hdcDoubleBuf, iX, iY, NULL); LineTo(hdcDoubleBuf, iZ, iT);
  431.                         }
  432.                     }
  433.  
  434.                     // 3.1 - Points
  435.                     for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++)
  436.                     {
  437.                         // Ignorer les points inexistants
  438.                         if (Vertices[iVertex].bEnabled == FALSE) continue;
  439.  
  440.                         // Ignorer les points cachés
  441.                         if (Vertices[iVertex].bHidden == TRUE) continue;
  442.  
  443.                         vVect1 = Vertices[iVertex].vPoint;
  444.  
  445.                         switch(lWActive)
  446.                         {
  447.                             case XDC_WID_TOP : // X et Z
  448.                                 iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  449.                                 iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef);
  450.                                 break;
  451.  
  452.                             case XDC_WID_FACE : // X et Y
  453.                                 iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  454.                                 iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  455.                                 break;
  456.                             
  457.                             case XDC_WID_SIDE : // Z et Y
  458.                                 iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef);
  459.                                 iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  460.                                 break;
  461.                         }
  462.  
  463.                         // Tracer le sommet du triangle (petite croix)
  464.                         lColor = Vertices[iVertex].bSelected ? XDC_COL_YELLOW : XDC_COL_DKBLUESK;
  465.                         SetPixel(hdcDoubleBuf, iX, iY, lColor);
  466.                         SetPixel(hdcDoubleBuf, iX - 1, iY, lColor);
  467.                         SetPixel(hdcDoubleBuf, iX + 1, iY, lColor);
  468.                         SetPixel(hdcDoubleBuf, iX, iY - 1, lColor);
  469.                         SetPixel(hdcDoubleBuf, iX, iY + 1, lColor);
  470.                     }
  471.  
  472.                     // 3.2 - VertexBuffers des objets de base
  473.                     for (int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++)
  474.                     {
  475.                         if (Objects[iObject].bEnabled == FALSE) continue;
  476.                         if (Objects[iObject].bHidden == TRUE) continue;
  477.  
  478.                         LPDIRECT3DVERTEXBUFFER7 vBuf = Objects[iObject].pShape -> GetVB();
  479.                         D3DVERTEXBUFFERDESC vbDesc;
  480.  
  481.                         vbDesc.dwSize = sizeof(vbDesc);
  482.                         vBuf -> GetVertexBufferDesc(&vbDesc);
  483.  
  484.                         if (vbDesc.dwFVF != D3DFVF_VERTEX) continue;
  485.  
  486.                         D3DVERTEX *vbAddr;
  487.                         unsigned long iSize;
  488.  
  489.                         vBuf -> Lock(DDLOCK_SURFACEMEMORYPTR, (void **) &vbAddr, &iSize);
  490.  
  491.                         for (unsigned iVertex = 0 ; iVertex < vbDesc.dwNumVertices ; iVertex++)
  492.                         {
  493.                             switch(lWActive)
  494.                             {
  495.                                 case XDC_WID_TOP : // X et Z
  496.                                     iX = (int) XDM_to2D(vbAddr[iVertex].x, fXmin, iWindowXMin, f3D2DXCoef);
  497.                                     iY = (int) XDM_to2D(vbAddr[iVertex].z, fZmin, iWindowYMin, f3D2DYCoef);
  498.                                     break;
  499.  
  500.                                 case XDC_WID_FACE : // X et Y
  501.                                     iX = (int) XDM_to2D(vbAddr[iVertex].x, fXmin, iWindowXMin, f3D2DXCoef);
  502.                                     iY = (int) XDM_to2D(vbAddr[iVertex].y, fYmin, iWindowYMin, f3D2DYCoef);
  503.                                     break;
  504.                                 
  505.                                 case XDC_WID_SIDE : // Z et Y
  506.                                     iX = (int) XDM_to2D(vbAddr[iVertex].z, fZmin, iWindowXMin, f3D2DXCoef);
  507.                                     iY = (int) XDM_to2D(vbAddr[iVertex].y, fYmin, iWindowYMin, f3D2DYCoef);
  508.                                     break;
  509.                             }
  510.  
  511.                             // Tracer le point (petite croix)
  512.                             lColor = Objects[iObject].bSelected ? XDC_COL_YELLOW : XDC_COL_DKPINK;
  513.                             SetPixel(hdcDoubleBuf, iX, iY, lColor);
  514.                             SetPixel(hdcDoubleBuf, iX - 1, iY, lColor);
  515.                             SetPixel(hdcDoubleBuf, iX + 1, iY, lColor);
  516.                             SetPixel(hdcDoubleBuf, iX, iY - 1, lColor);
  517.                             SetPixel(hdcDoubleBuf, iX, iY + 1, lColor);
  518.                         }
  519.  
  520.                         vBuf -> Unlock();
  521.                         vBuf -> Release();
  522.  
  523.                         // Tracer l'origine de l'objet (qui sert aussi de handle)
  524.                         switch(lWActive)
  525.                         {
  526.                             case XDC_WID_TOP : // X et Z
  527.                                 iX = (int) XDM_to2D(Objects[iObject].vOrigin.x, fXmin, iWindowXMin, f3D2DXCoef);
  528.                                 iY = (int) XDM_to2D(Objects[iObject].vOrigin.z, fZmin, iWindowYMin, f3D2DYCoef);
  529.                                 break;
  530.  
  531.                             case XDC_WID_FACE : // X et Y
  532.                                 iX = (int) XDM_to2D(Objects[iObject].vOrigin.x, fXmin, iWindowXMin, f3D2DXCoef);
  533.                                 iY = (int) XDM_to2D(Objects[iObject].vOrigin.y, fYmin, iWindowYMin, f3D2DYCoef);
  534.                                 break;
  535.                             
  536.                             case XDC_WID_SIDE : // Z et Y
  537.                                 iX = (int) XDM_to2D(Objects[iObject].vOrigin.z, fZmin, iWindowXMin, f3D2DXCoef);
  538.                                 iY = (int) XDM_to2D(Objects[iObject].vOrigin.y, fYmin, iWindowYMin, f3D2DYCoef);
  539.                                 break;
  540.                         }
  541.  
  542.                         // Tracer le point (petite croix)
  543.                         lColor = Objects[iObject].bSelected ? XDC_COL_YELLOW : XDC_COL_GREEN;
  544.                         SetPixel(hdcDoubleBuf, iX - 1, iY, lColor);
  545.                         SetPixel(hdcDoubleBuf, iX + 1, iY, lColor);
  546.                         SetPixel(hdcDoubleBuf, iX, iY - 1, lColor);
  547.                         SetPixel(hdcDoubleBuf, iX, iY + 1, lColor);
  548.                         
  549.                     }
  550.  
  551.                     // 4 - Lampes
  552.                     for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++)
  553.                     {
  554.                         // Ignorer les lampes inexistantes
  555.                         if (Lampes[iLamp].bEnabled == FALSE) continue;
  556.  
  557.                         if (Lampes[iLamp].bSelected == FALSE)
  558.                             SelectObject(hdcDoubleBuf, hpenRed);
  559.                         else
  560.                             SelectObject(hdcDoubleBuf, hpenYellow);
  561.  
  562.                         vVect1 = Lampes[iLamp].lLamp.dvPosition;
  563.  
  564.                         switch(lWActive)
  565.                         {
  566.                             case XDC_WID_TOP : // X et Z
  567.                                 iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  568.                                 iY = (int) XDM_to2D(vVect1.z, fZmin, iWindowYMin, f3D2DYCoef);
  569.                                 break;
  570.  
  571.                             case XDC_WID_FACE : // X et Y
  572.                                 iX = (int) XDM_to2D(vVect1.x, fXmin, iWindowXMin, f3D2DXCoef);
  573.                                 iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  574.                                 break;
  575.                             
  576.                             case XDC_WID_SIDE : // Z et Y
  577.                                 iX = (int) XDM_to2D(vVect1.z, fZmin, iWindowXMin, f3D2DXCoef);
  578.                                 iY = (int) XDM_to2D(vVect1.y, fYmin, iWindowYMin, f3D2DYCoef);
  579.                                 break;
  580.                         }
  581.                         Ellipse(hdcDoubleBuf, iX - 3, iY - 3, iX + 3, iY + 3);
  582.                     }
  583.  
  584.                     // Libérer le clipping du double buffer
  585.                     SelectClipRgn(hdcDoubleBuf, NULL);
  586.  
  587.                     // Restaurer les objets par défaut du double buffer
  588.                     SelectObject(hdcDoubleBuf, hSaveBrush);
  589.                     SelectObject(hdcDoubleBuf, hSavePen);
  590.                 }
  591. _skip:
  592.                 // BitBlitter le double buffer dans le triple buffer
  593.                 BitBlt(hdcTripleBuf, 0, 0, rExtRect.right - rExtRect.left, rExtRect.bottom - rExtRect.top,
  594.                        hdcDoubleBuf, 0, 0, SRCCOPY);
  595.                 
  596.                 // Définir zone de clipping du triple buffer : rectangle interne
  597.                 IntersectClipRect(hdcTripleBuf,iWindowXMin + 1, iWindowYMax + 1, iWindowXMax - 1, iWindowYMin - 1);
  598.  
  599.                 // 5 - Tracer le curseur principal
  600.                 switch(lWActive)
  601.                 {
  602.                     case XDC_WID_TOP : // X et Z
  603.                         iX = (int) XDM_to2D(Cursor1.x, fXmin, iWindowXMin, f3D2DXCoef);
  604.                         iY = (int) XDM_to2D(Cursor1.z, fZmin, iWindowYMin, f3D2DYCoef);
  605.                         iZ = (int) XDM_to2D(Cursor1.x - (fXmax - fXmin) / XDC_ZONE, fXmin, iWindowXMin, f3D2DXCoef);
  606.                         iT = (int) XDM_to2D(Cursor1.z - (fXmax - fXmin) / XDC_ZONE, fZmin, iWindowYMin, f3D2DYCoef);
  607.                         break;
  608.  
  609.                     case XDC_WID_FACE : // X et Y
  610.                         iX = (int) XDM_to2D(Cursor1.x, fXmin, iWindowXMin, f3D2DXCoef);
  611.                         iY = (int) XDM_to2D(Cursor1.y, fYmin, iWindowYMin, f3D2DYCoef);
  612.                         iZ = (int) XDM_to2D(Cursor1.x - (fXmax - fXmin) / XDC_ZONE, fXmin, iWindowXMin, f3D2DXCoef);
  613.                         iT = (int) XDM_to2D(Cursor1.y - (fXmax - fXmin) / XDC_ZONE, fYmin, iWindowYMin, f3D2DYCoef);
  614.                         break;
  615.                     
  616.                     case XDC_WID_SIDE : // Z et Y
  617.                         iX = (int) XDM_to2D(Cursor1.z, fZmin, iWindowXMin, f3D2DXCoef);
  618.                         iY = (int) XDM_to2D(Cursor1.y, fYmin, iWindowYMin, f3D2DYCoef);
  619.                         iZ = (int) XDM_to2D(Cursor1.z - (fXmax - fXmin) / XDC_ZONE, fZmin, iWindowXMin, f3D2DXCoef);
  620.                         iT = (int) XDM_to2D(Cursor1.y - (fXmax - fXmin) / XDC_ZONE, fYmin, iWindowYMin, f3D2DYCoef);
  621.                         break;
  622.                 }
  623.  
  624.                 hSavePen = (HPEN) SelectObject(hdcTripleBuf, (cTool == XDC_TOOL_UNSELECT ? hpenDkBlueSk : hpenYellow));
  625.                 
  626.                 // Tracer la zone de tolérance
  627.                 MoveToEx(hdcTripleBuf, iZ, iT, NULL); LineTo(hdcTripleBuf, iZ + 2 * (iX - iZ), iT);
  628.                 MoveToEx(hdcTripleBuf, iZ, iT, NULL); LineTo(hdcTripleBuf, iZ, iT + 2 * (iY - iT));
  629.  
  630.                 if ((cTool == XDC_TOOL_SELECT) || (cTool == XDC_TOOL_UNSELECT))
  631.                 {
  632.                     MoveToEx(hdcTripleBuf, iZ, iT + 2 * (iY - iT), NULL); LineTo(hdcTripleBuf, iZ + 2 * (iX - iZ), iT + 2 * (iY - iT));
  633.                     MoveToEx(hdcTripleBuf, iZ + 2 * (iX - iZ), iT, NULL); LineTo(hdcTripleBuf, iZ + 2 * (iX - iZ), iT + 2 * (iY - iT));
  634.                 }
  635.  
  636.                 // Rappeller l'outil courant à coté du curseur
  637.                 if (cTool != XDC_TOOL_NONE)
  638.                     ExtTextOut(hdcTripleBuf, iX + 2, iY  - 13, 0, NULL, &cTool, 1, NULL);
  639.  
  640.                 // Tracer le curseur 1
  641.                 SelectObject(hdcTripleBuf, hpenCyan);
  642.                 MoveToEx(hdcTripleBuf, iX - 9, iY, NULL); LineTo(hdcTripleBuf, iX + 10, iY);
  643.                 MoveToEx(hdcTripleBuf, iX, iY - 9, NULL); LineTo(hdcTripleBuf, iX, iY + 10);
  644.  
  645.                 // 6 - Tracer le curseur 2
  646.                 switch(lWActive)
  647.                 {
  648.                     case XDC_WID_TOP : // X et Z
  649.                         iX = (int) XDM_to2D(Cursor2.x, fXmin, iWindowXMin, f3D2DXCoef);
  650.                         iY = (int) XDM_to2D(Cursor2.z, fZmin, iWindowYMin, f3D2DYCoef);
  651.                         break;
  652.  
  653.                     case XDC_WID_FACE : // X et Y
  654.                         iX = (int) XDM_to2D(Cursor2.x, fXmin, iWindowXMin, f3D2DXCoef);
  655.                         iY = (int) XDM_to2D(Cursor2.y, fYmin, iWindowYMin, f3D2DYCoef);
  656.                         break;
  657.                     
  658.                     case XDC_WID_SIDE : // Z et Y
  659.                         iX = (int) XDM_to2D(Cursor2.z, fZmin, iWindowXMin, f3D2DXCoef);
  660.                         iY = (int) XDM_to2D(Cursor2.y, fYmin, iWindowYMin, f3D2DYCoef);
  661.                         break;
  662.                 }
  663.                 Ellipse(hdcTripleBuf, iX - 3, iY - 3, iX + 3, iY + 3);
  664.  
  665.                 // 7 - Tracer le curseur 3
  666.                 switch(lWActive)
  667.                 {
  668.                     case XDC_WID_TOP : // X et Z
  669.                         iX = (int) XDM_to2D(Cursor3.x, fXmin, iWindowXMin, f3D2DXCoef);
  670.                         iY = (int) XDM_to2D(Cursor3.z, fZmin, iWindowYMin, f3D2DYCoef);
  671.                         break;
  672.  
  673.                     case XDC_WID_FACE : // X et Y
  674.                         iX = (int) XDM_to2D(Cursor3.x, fXmin, iWindowXMin, f3D2DXCoef);
  675.                         iY = (int) XDM_to2D(Cursor3.y, fYmin, iWindowYMin, f3D2DYCoef);
  676.                         break;
  677.                     
  678.                     case XDC_WID_SIDE : // Z et Y
  679.                         iX = (int) XDM_to2D(Cursor3.z, fZmin, iWindowXMin, f3D2DXCoef);
  680.                         iY = (int) XDM_to2D(Cursor3.y, fYmin, iWindowYMin, f3D2DYCoef);
  681.                         break;
  682.                 }
  683.                 MoveToEx(hdcTripleBuf, iX - 4, iY - 4, NULL); LineTo(hdcTripleBuf, iX + 5, iY + 5);
  684.                 MoveToEx(hdcTripleBuf, iX - 4, iY + 4, NULL); LineTo(hdcTripleBuf, iX + 5, iY - 5);
  685.  
  686.                 // 8 - Tracer l'observateur
  687.                 SelectObject(hdcTripleBuf, hpenWhite);
  688.                 switch(lWActive)
  689.                 {
  690.                     case XDC_WID_TOP : // X et Z
  691.                         iX = (int) XDM_to2D(Observer.x, fXmin, iWindowXMin, f3D2DXCoef);
  692.                         iY = (int) XDM_to2D(Observer.z, fZmin, iWindowYMin, f3D2DYCoef);
  693.                         break;
  694.  
  695.                     case XDC_WID_FACE : // X et Y
  696.                         iX = (int) XDM_to2D(Observer.x, fXmin, iWindowXMin, f3D2DXCoef);
  697.                         iY = (int) XDM_to2D(Observer.y, fYmin, iWindowYMin, f3D2DYCoef);
  698.                         break;
  699.                     
  700.                     case XDC_WID_SIDE : // Z et Y
  701.                         iX = (int) XDM_to2D(Observer.z, fZmin, iWindowXMin, f3D2DXCoef);
  702.                         iY = (int) XDM_to2D(Observer.y, fYmin, iWindowYMin, f3D2DYCoef);
  703.                         break;
  704.                 }
  705.                 Ellipse(hdcTripleBuf, iX - 2, iY - 2, iX + 3, iY + 3);
  706.  
  707.                 // 9 - Tracer la cible et le segment caméra / cible
  708.                 switch(lWActive)
  709.                 {
  710.                     case XDC_WID_TOP : // X et Z
  711.                         iZ = (int) XDM_to2D(Target.x, fXmin, iWindowXMin, f3D2DXCoef);
  712.                         iT = (int) XDM_to2D(Target.z, fZmin, iWindowYMin, f3D2DYCoef);
  713.                         break;
  714.  
  715.                     case XDC_WID_FACE : // X et Y
  716.                         iZ = (int) XDM_to2D(Target.x, fXmin, iWindowXMin, f3D2DXCoef);
  717.                         iT = (int) XDM_to2D(Target.y, fYmin, iWindowYMin, f3D2DYCoef);
  718.                         break;
  719.                     
  720.                     case XDC_WID_SIDE : // Z et Y
  721.                         iZ = (int) XDM_to2D(Target.z, fZmin, iWindowXMin, f3D2DXCoef);
  722.                         iT = (int) XDM_to2D(Target.y, fYmin, iWindowYMin, f3D2DYCoef);
  723.                         break;
  724.                 }
  725.                 MoveToEx(hdcTripleBuf, iZ - 2, iT - 2, NULL); LineTo(hdcTripleBuf, iZ + 3, iT + 3);
  726.                 MoveToEx(hdcTripleBuf, iZ - 2, iT + 2, NULL); LineTo(hdcTripleBuf, iZ + 3, iT - 3);
  727.                 MoveToEx(hdcTripleBuf, iX, iY, NULL); LineTo(hdcTripleBuf, iZ, iT);
  728.  
  729.                 // 10 - Coordonnées courantes
  730.                 if (bCoords)
  731.                 {
  732.                     sprintf(cCoords, "(%012.5f, %012.5f, %012.5f)", vTracker.x, vTracker.y, vTracker.z);
  733.                     ExtTextOut(hdcTripleBuf, 18, 10, 0, NULL, cCoords, strlen(cCoords), NULL);
  734.                 }
  735.  
  736.                 // Libérer le clipping du triple buffer
  737.                 SelectClipRgn(hdcTripleBuf, NULL);
  738.  
  739.                 // BitBlitter le triple buffer dans la fenêtre
  740.                 BitBlt(hdcWin, rExtRect.left, rExtRect.top, rExtRect.right - rExtRect.left, rExtRect.bottom - rExtRect.top,
  741.                        hdcTripleBuf, 0, 0, SRCCOPY);
  742.  
  743.                 // Restaurer les objets par défaut du triple buffer
  744.                 SelectObject(hdcTripleBuf, hSavePen);
  745.                 
  746.                 EndPaint(hWnd, &hPStruct);
  747.                 break;
  748.             }
  749.  
  750.         case WM_LBUTTONDOWN : //**************** C L I C K  G A U C H E *******************
  751.             RECT rClipCurseur;
  752.  
  753.             // Si on est déjà en tracking curseur alors ne rien faire
  754.             if (bTracking) break;
  755.  
  756.             // Noter le qualifier (touches enfoncées au moment du click)
  757.             wModifier = wParam;
  758.  
  759.             // Précalculer les offsets (déplacement, zoom, etc.) en fonction du modifieur
  760.             fXs = (fXmax - fXmin) / ((wModifier & MK_SHIFT) ? 4.f : 8.f),
  761.             fYs = (fYmax - fYmin) / ((wModifier & MK_SHIFT) ? 4.f : 8.f),
  762.             fZs = (fZmax - fZmin) / ((wModifier & MK_SHIFT) ? 4.f : 8.f);
  763.             
  764.             // Vérifier si le click n'est pas dans les boutons Sculpt.
  765.             pClick.x = LOWORD(lParam);
  766.             pClick.y = HIWORD(lParam);
  767.  
  768.             if (XDM_BoutonClic(XDC_GID_MakeTri, pClick)) //********* Bouton MakeTri
  769.             {
  770.                 int iPoint[3], iPoints = 0;
  771.  
  772.                 // Compter et mémoriser les points sélectionnés (jusqu'à 3)
  773.                 for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++)
  774.                     if (bIsVertexSelected(iVertex))
  775.                     {
  776.                         if (iPoints < 3) iPoint[iPoints] = iVertex;
  777.                         iPoints++;
  778.                     }
  779.  
  780.                 // - soit il existe exactement 2 points sélectionnés et on fait une arête avec
  781.                 //   si elle n'existe pas déjà
  782.                 //   (on ne transforme pas 3 points reliés par 3 arêtes en triangle ***???)
  783.                 if (iPoints == 2)
  784.                 {
  785.                     vTrace("Deux points sélectionnés -> création arête");
  786.  
  787.                     if (-1 == iFindEdge(iPoint[0], iPoint[1]))
  788.                     {
  789.                         iMakeEdge(iPoint[0], iPoint[1]);
  790.                         vForce2DRefresh(XDC_MODE_COMPLET);
  791.                         vForce3DRefresh(XDC_MODE_COMPLET);
  792.                     }
  793.                     else
  794.                         vTrace("*** E0001 : L'arête existe déjà");
  795.                     break;
  796.                 }
  797.  
  798.                 // - soit il existe exactement 3 points sélectionnés et on fait un triangle avec
  799.                 //   (en supprimant les arêtes éventuelles existant entre ces 3 points) s'il n'existe pas déjà
  800.                 if (iPoints == 3)
  801.                 {
  802.                     vTrace("Trois points sélectionnés -> création facette");
  803.  
  804.                     if (-1 == iFindTriangle(iPoint[0], iPoint[1], iPoint[2]))
  805.                     {
  806.                         iMakeTriangle(iPoint[0], iPoint[1], iPoint[2], rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX);
  807.                         vForce2DRefresh(XDC_MODE_COMPLET);
  808.                         vForce3DRefresh(XDC_MODE_COMPLET);
  809.                     }
  810.                     else
  811.                         vTrace("*** E0002 : Le triangle existe déjà");
  812.                     break;
  813.                 }
  814.  
  815.                 // - soit il existe exactement 0 points sélectionnés et on fait un triangle entre
  816.                 //   les 3 curseurs s'il n'existe pas déjà
  817.                 if (iPoints == 0)
  818.                 {
  819.                     vTrace("Zéro points sélectionnés -> création facette avec les 3 curseurs");
  820.                     iPoint[0] = iMakeVertex(Cursor2, XDC_ALLOWSAME),
  821.                     iPoint[1] = iMakeVertex(Cursor1, XDC_ALLOWSAME),
  822.                     iPoint[2] = iMakeVertex(Cursor3, XDC_ALLOWSAME);
  823.  
  824.                     if (-1 == iFindTriangle(iPoint[0], iPoint[1], iPoint[2]))
  825.                     {
  826.                         iMakeTriangle(iPoint[0], iPoint[1], iPoint[2], rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX, rand() * 255 / RAND_MAX);
  827.                         vForce2DRefresh(XDC_MODE_COMPLET);
  828.                         vForce3DRefresh(XDC_MODE_COMPLET);
  829.                     }
  830.                     else
  831.                         vTrace("*** E0003 : Le triangle existe déjà");
  832.                     break;
  833.                 }
  834.  
  835.                 vTrace("*** E0004 : Nombre de points sélectionnés incorrect (doit être 0, 2 ou 3)");
  836.                 break;
  837.             }
  838.  
  839.             if (XDM_BoutonClic(XDC_GID_ZoomOut, pClick)) //********* Bouton Zoom Out
  840.             {
  841.                 fXmin -= fXs; fXmax += fXs;
  842.                 fYmin -= fYs; fYmax += fYs;
  843.                 fZmin -= fZs; fZmax += fZs;
  844.  
  845.                 vForce2DRefresh(XDC_MODE_COMPLET);
  846.                 break;
  847.             }
  848.  
  849.             if (XDM_BoutonClic(XDC_GID_ZoomIn, pClick)) //********* Bouton Zoom In
  850.             {
  851.                 fXmin += fXs; fXmax -= fXs;
  852.                 fYmin += fYs; fYmax -= fYs;
  853.                 fZmin += fZs; fZmax -= fZs;
  854.  
  855.                 vForce2DRefresh(XDC_MODE_COMPLET);
  856.                 break;
  857.             }
  858.  
  859.             if (    (XDM_BoutonClic(XDC_GID_RotClock, pClick)) //********* Bouton Rotation clockwise
  860.                  || (XDM_BoutonClic(XDC_GID_RotAnti, pClick))  //********* Bouton Rotation anti-clockwise
  861.                )
  862.             {
  863.                 D3DMATRIX mRot;
  864.                 float fAngle = g_PI / (wModifier & MK_SHIFT ? 10.f : 20.f);
  865.  
  866.                 if (XDM_BoutonClic(XDC_GID_RotClock, pClick)) fAngle *= -1.f;
  867.  
  868.                 // Préparer la matrice de rotation
  869.                 switch(lWActive)
  870.                 {
  871.                 case XDC_WID_TOP : // X et Z
  872.                     D3DUtil_SetRotateYMatrix(mRot, -fAngle);
  873.                     break;
  874.  
  875.                 case XDC_WID_FACE : // X et Y
  876.                     D3DUtil_SetRotateZMatrix(mRot, fAngle);
  877.                     break;
  878.                 
  879.                 case XDC_WID_SIDE : // Z et Y
  880.                     D3DUtil_SetRotateXMatrix(mRot, -fAngle);
  881.                     break;
  882.                 }
  883.  
  884.                 // Appliquer la matrice aux sommets sélectionnés
  885.                 for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++)
  886.                     if (bIsVertexSelected(iVertex))
  887.                     {
  888.                         // Changer de repère => Cursor1
  889.                         D3DVECTOR vTrans = Vertices[iVertex].vPoint - Cursor1;
  890.                     
  891.                         // Appliquer la rotation au point translaté
  892.                         D3DMath_VectorMatrixMultiply(vTrans,
  893.                                                      vTrans,
  894.                                                      mRot);
  895.  
  896.                         // Remettre dans le repère d'origine
  897.                         Vertices[iVertex].vPoint = vTrans + Cursor1;
  898.                     }
  899.                 
  900.                 // Recalculer les sommets des triangles ayant des sommets sélectionnés
  901.                 for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  902.                     if (bIsTrianglePartiallySelected(iTriangle))
  903.                         bUpdateD3DTri(iTriangle);
  904.  
  905.                 // Appliquer la matrice de rotation aux objets D3D sélectionnés
  906.                 for (int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++)
  907.                     if ((Objects[iObject].bEnabled) && (Objects[iObject].bSelected))
  908.                     {
  909.                         LPDIRECT3DVERTEXBUFFER7 vBuf = Objects[iObject].pShape -> GetVB();
  910.                         D3DVERTEXBUFFERDESC vbDesc;
  911.                         D3DVECTOR vTrans;
  912.  
  913.                         vbDesc.dwSize = sizeof(vbDesc);
  914.                         vBuf -> GetVertexBufferDesc(&vbDesc);
  915.  
  916.                         if (vbDesc.dwFVF != D3DFVF_VERTEX) return FALSE;
  917.  
  918.                         D3DVERTEX *vbAddr;
  919.                         unsigned long iSize;
  920.  
  921.                         vBuf -> Lock(DDLOCK_SURFACEMEMORYPTR, (void **) &vbAddr, &iSize);
  922.  
  923.                         for (unsigned iVertex = 0 ; iVertex < vbDesc.dwNumVertices ; iVertex++)
  924.                         {
  925.  
  926.                             // A - Traiter le point
  927.                             // Changer de repère => Cursor1
  928.                             vTrans = D3DVECTOR(
  929.                                 vbAddr[iVertex].x - Cursor1.x,
  930.                                 vbAddr[iVertex].y - Cursor1.y,
  931.                                 vbAddr[iVertex].z - Cursor1.z);
  932.                         
  933.                             // Appliquer la rotation au point translaté
  934.                             D3DMath_VectorMatrixMultiply(vTrans,
  935.                                                          vTrans,
  936.                                                          mRot);
  937.  
  938.                             // Remettre dans le repère d'origine
  939.                             vTrans += Cursor1;
  940.                             vbAddr[iVertex].x = vTrans.x;
  941.                             vbAddr[iVertex].y = vTrans.y;
  942.                             vbAddr[iVertex].z = vTrans.z;
  943.  
  944.                             // B - Traiter le vecteur normal
  945.                             vTrans = D3DVECTOR(
  946.                                 vbAddr[iVertex].nx,
  947.                                 vbAddr[iVertex].ny,
  948.                                 vbAddr[iVertex].nz);
  949.                         
  950.                             D3DMath_VectorMatrixMultiply(vTrans,
  951.                                                          vTrans,
  952.                                                          mRot);
  953.  
  954.                             vbAddr[iVertex].nx = vTrans.x;
  955.                             vbAddr[iVertex].ny = vTrans.y;
  956.                             vbAddr[iVertex].nz = vTrans.z;
  957.  
  958.                         }
  959.  
  960.                         vBuf -> Unlock();
  961.                         vBuf -> Release();
  962.  
  963.                         // Traiter l'origine locale objet
  964.                         vTrans = Objects[iObject].vOrigin - Cursor1;
  965.                         D3DMath_VectorMatrixMultiply(vTrans,
  966.                                                      vTrans,
  967.                                                      mRot);
  968.                         Objects[iObject].vOrigin = vTrans + Cursor1;
  969.                     }
  970.  
  971.                 // Raffraichir les vues 2D et 3D    
  972.                 vForce2DRefresh(XDC_MODE_COMPLET);
  973.                 vForce3DRefresh(XDC_MODE_COMPLET);
  974.                 break;
  975.             }
  976.  
  977.             if (XDM_BoutonClic(XDC_GID_Reverse, pClick)) // ********* Bouton reverse (?)
  978.             {
  979.                 // vForce2DRefresh(XDC_MODE_COMPLET);
  980.                 break;
  981.             }
  982.  
  983.             if (XDM_BoutonClic(XDC_GID_Grab, pClick)) // ********* Bouton Grabber (toggle)
  984.             {
  985.                 cTool = (cTool == XDC_TOOL_GRAB ? XDC_TOOL_NONE : XDC_TOOL_GRAB);
  986.                 vForce2DRefresh(XDC_MODE_PARTIEL);
  987.                 vUpdateMenu();
  988.                 break;
  989.             }
  990.  
  991.             if (XDM_BoutonClic(XDC_GID_GoRight, pClick)) //********* Bouton Go Right
  992.             {
  993.                 switch(lWActive)
  994.                 {
  995.                     case XDC_WID_TOP : // X et Z
  996.                     case XDC_WID_FACE : // X et Y
  997.                         fXmin += fXs; fXmax += fXs;
  998.                         break;
  999.                     case XDC_WID_SIDE : // Z et Y
  1000.                         fZmin += fZs; fZmax += fZs;
  1001.                         break;
  1002.                 }
  1003.  
  1004.                 vForce2DRefresh(XDC_MODE_COMPLET);
  1005.                 break;
  1006.             }
  1007.  
  1008.             if (XDM_BoutonClic(XDC_GID_GoUp, pClick)) //********* Bouton Go up
  1009.             {
  1010.                 switch(lWActive)
  1011.                 {
  1012.                     case XDC_WID_TOP : // X et Z
  1013.                         fZmin += fZs; fZmax += fZs;
  1014.                         break;
  1015.                     case XDC_WID_FACE : // X et Y
  1016.                     case XDC_WID_SIDE : // Z et Y
  1017.                         fYmin += fYs; fYmax += fYs;
  1018.                         break;
  1019.                 }
  1020.  
  1021.                 vForce2DRefresh(XDC_MODE_COMPLET);
  1022.                 break;
  1023.             }
  1024.  
  1025.             if (XDM_BoutonClic(XDC_GID_GoLeft, pClick)) //********* Bouton Go left
  1026.             {
  1027.                 switch(lWActive)
  1028.                 {
  1029.                     case XDC_WID_TOP : // X et Z
  1030.                     case XDC_WID_FACE : // X et Y
  1031.                         fXmin -= fXs; fXmax -= fXs;
  1032.                         break;
  1033.                     case XDC_WID_SIDE : // Z et Y
  1034.                         fZmin -= fZs; fZmax -= fZs;
  1035.                         break;
  1036.                 }
  1037.  
  1038.                 vForce2DRefresh(XDC_MODE_COMPLET);
  1039.                 break;
  1040.             }
  1041.  
  1042.             if (XDM_BoutonClic(XDC_GID_GoDown, pClick)) //********* Bouton Go down
  1043.             {
  1044.                 switch(lWActive)
  1045.                 {
  1046.                     case XDC_WID_TOP : // X et Z
  1047.                         fZmin -= fZs; fZmax -= fZs;
  1048.                         break;
  1049.                     case XDC_WID_FACE : // X et Y
  1050.                     case XDC_WID_SIDE : // Z et Y
  1051.                         fYmin -= fYs; fYmax -= fYs;
  1052.                         break;
  1053.                 }
  1054.  
  1055.                 vForce2DRefresh(XDC_MODE_COMPLET);
  1056.                 break;
  1057.             }
  1058.  
  1059.             if (XDM_BoutonClic(XDC_GID_AddPoint, pClick)) //********* Bouton Add Point
  1060.             {
  1061.                 PostMessage(hWnd, WM_CHAR, 'p', 0);
  1062.                 break;
  1063.             }
  1064.  
  1065.             if (XDM_BoutonClic(XDC_GID_Center, pClick)) //********* Bouton Center
  1066.             {
  1067.                 float    fXs = (fXmax - fXmin) / 2.f,
  1068.                         fYs = (fYmax - fYmin) / 2.f,
  1069.                         fZs = (fZmax - fZmin) / 2.f;
  1070.                 
  1071.                 fXmin = Cursor1.x - fXs; fXmax = Cursor1.x + fXs;
  1072.                 fYmin = Cursor1.y - fYs; fYmax = Cursor1.y + fYs;
  1073.                 fZmin = Cursor1.z - fZs; fZmax = Cursor1.z + fZs;
  1074.  
  1075.                 vForce2DRefresh(XDC_MODE_COMPLET);
  1076.                 break;
  1077.             }
  1078.  
  1079.             // Si click dans le rectangle interne, alors :
  1080.             // - déclencher le tracking (curseur, observer ou target en fonction du qualifier
  1081.             // - n'autoriser le déplacement que dans le subrect client (clipcursor)
  1082.             // - initialiser le tracking (MOUSEMOVE)
  1083.             if (PtInRect(&rIntRect, pClick))
  1084.             {
  1085.                 CopyRect(&rClipCurseur, &rIntRect);
  1086.                 ClientToScreen(hWnd, (POINT *) &rClipCurseur);
  1087.                 ClientToScreen(hWnd, (POINT *) &rClipCurseur + 1);
  1088.                 ClipCursor(&rClipCurseur);
  1089.  
  1090.                 bTracking = TRUE;
  1091.                 PostMessage(hWnd, WM_MOUSEMOVE, wParam, lParam);
  1092.                 break;
  1093.             }
  1094.  
  1095.             // Click dans zone cliente, ni rectangle interne ni gadgets sKulpt : popup menu
  1096.             // avec menu édition
  1097.             hMenu = GetSubMenu(GetMenu(hWndMenu), 1);
  1098.             ClientToScreen(hWnd, &pClick);
  1099.             TrackPopupMenu (hMenu, 0, pClick.x, pClick.y, 0, hWnd, NULL);
  1100.             break;
  1101.  
  1102.         case WM_LBUTTONDBLCLK:
  1103.             pClick.x = LOWORD(lParam);
  1104.             pClick.y = HIWORD(lParam);
  1105.  
  1106.             // Si le double click est dans le rectangle interne alors toggler la sélection du noeud indiqué
  1107.             // en envoyant le message ID_EDITION_SLECTIONNER_NOEUDINDIQU à la fenêtre menu avec lParam = XDC_TOGGLE
  1108.             // Sinon, traiter le message comme un simple click
  1109.             if (PtInRect(&rIntRect, pClick))
  1110.                 PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_SINGLETOGGLE);
  1111.             else
  1112.                 PostMessage(hWnd, WM_LBUTTONDOWN, wParam, lParam);
  1113.             break;
  1114.  
  1115.         case WM_LBUTTONUP : //******************** R E L A C H E  B O U T O N  G A U C H E ******
  1116.             // Si on n'est pas en mode tracking, ne rien faire
  1117.             // (ou envoyer les coordonnées à la dlg d'acquisition des trous des formes à remplir si elle est active).
  1118.             if (hHoleDlgActive)
  1119.             {
  1120.                 switch(lWActive)
  1121.                 {
  1122.                     case XDC_WID_TOP : // X et Z
  1123.                         dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fXmin, iWindowXMin, f3D2DXCoef);
  1124.                         dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fZmin, iWindowYMin, f3D2DYCoef);
  1125.                         break;
  1126.                     case XDC_WID_FACE : // X et Y
  1127.                         dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fXmin, iWindowXMin, f3D2DXCoef);
  1128.                         dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fYmin, iWindowYMin, f3D2DYCoef);
  1129.                         break;
  1130.                     case XDC_WID_SIDE : // Z et Y
  1131.                         dHoles[iHoles * 2 + 0] = XDM_to3D(LOWORD(lParam), fZmin, iWindowXMin, f3D2DXCoef);
  1132.                         dHoles[iHoles * 2 + 1] = XDM_to3D(HIWORD(lParam), fYmin, iWindowYMin, f3D2DYCoef);
  1133.                         break;
  1134.                 }
  1135.                 iHoles++;
  1136.                 SendMessage(hHoleDlgActive, WM_USER+1, 0, 0);
  1137.             }
  1138.  
  1139.             if (!bTracking)
  1140.                 break;
  1141.  
  1142.             // Si on est en mode tracking, arrêter le mode tracking et supprimer le clipping.
  1143.             bTracking = FALSE;
  1144.             ClipCursor(NULL);
  1145.             break;
  1146.  
  1147.         case WM_CHAR : //************************* F R A P P E  C L A V I E R ********************
  1148.             PostMessage(hWndMenu, uMsg, wParam, lParam);
  1149.             break;
  1150.  
  1151.         case WM_MOUSEMOVE : //****************** M O U V E M E N T  S O U R I S *************
  1152.             D3DVECTOR *pObject;
  1153.  
  1154.             // Si on n'est pas en tracking alors on ne fait rien.
  1155.             if (!bTracking) break;
  1156.  
  1157.             // Déterminer l'objet à déplacer en fonction des qualifiers du WM_LBUTTONDOWN
  1158.             pObject = &Cursor1;
  1159.             if (wModifier & MK_MBUTTON)    pObject = &Target;
  1160.             if (wModifier & MK_RBUTTON)    pObject = &Observer;
  1161.             if (wModifier & MK_CONTROL)    pObject = &Cursor2;
  1162.             if (wModifier & MK_SHIFT)    pObject = &Cursor3;
  1163.  
  1164.             // Mémoriser l'ancien vecteur
  1165.             vVect1 = *pObject;
  1166.  
  1167.             // Déterminer les nouvelles coordonnées 2D de l'objet à déplacer
  1168.             iX = LOWORD(lParam);  // horizontal position 
  1169.             iY = HIWORD(lParam);  // vertical position
  1170.  
  1171.             // Mettre à jour les coordonnées 3D de l'objet à déplacer
  1172.             switch(lWActive)
  1173.             {
  1174.                 case XDC_WID_TOP : // X et Z
  1175.                     pObject -> x = XDM_to3D(iX, fXmin, iWindowXMin, f3D2DXCoef);
  1176.                     pObject -> z = XDM_to3D(iY, fZmin, iWindowYMin, f3D2DYCoef);
  1177.                     break;
  1178.                 case XDC_WID_FACE : // X et Y
  1179.                     pObject -> x = XDM_to3D(iX, fXmin, iWindowXMin, f3D2DXCoef);
  1180.                     pObject -> y = XDM_to3D(iY, fYmin, iWindowYMin, f3D2DYCoef);
  1181.                     break;
  1182.                 case XDC_WID_SIDE : // Z et Y
  1183.                     pObject -> z = XDM_to3D(iX, fZmin, iWindowXMin, f3D2DXCoef);
  1184.                     pObject -> y = XDM_to3D(iY, fYmin, iWindowYMin, f3D2DYCoef);
  1185.                     break;
  1186.             }
  1187.  
  1188.             // Si la grille est activée, snapper l'objet à la grille (en x/y/z)
  1189.             if (bGrid)
  1190.             {
  1191.                 pObject -> x = XDM_toGrid(pObject -> x);
  1192.                 pObject -> y = XDM_toGrid(pObject -> y);
  1193.                 pObject -> z = XDM_toGrid(pObject -> z);
  1194.             }
  1195.  
  1196.             // Mémoriser les coordonnées pour l'affichage des coordonnées
  1197.             if (bCoords) vTracker = *pObject;
  1198.  
  1199.             // Si on a déplacé l'observer ou le target, mettre à jour la VIEW MATRIX
  1200.             // (la vue 3D se met automatiquement à jour par timer dans 3dwndproc)
  1201.             if ((pObject == &Target) || (pObject == &Observer))
  1202.             {
  1203.                 D3DUtil_SetViewMatrix(matView,
  1204.                           Observer,    // From
  1205.                           Target,    // To
  1206.                           D3DVECTOR(0.f, 0.f, 0.f));
  1207.  
  1208.                 // Mettre à jour les variables d'état du pipe D3D
  1209.                 vSetD3DState();
  1210.  
  1211.                 // Recalculer la scène
  1212.                 vForce3DRefresh(XDC_MODE_COMPLET);
  1213.             }
  1214.  
  1215.             // Si on a un outil sélectionné, appliquer l'outil à la sélection
  1216.             if ((pObject == &Cursor1) && (cTool != XDC_TOOL_NONE))
  1217.             {
  1218.                 switch(cTool)
  1219.                 {
  1220.                     case XDC_TOOL_SELECT:
  1221.                         PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_SELECTALL);
  1222.                         break;
  1223.  
  1224.                     case XDC_TOOL_UNSELECT:
  1225.                         PostMessage(hWndMenu, WM_COMMAND, ID_EDITION_SLECTIONNER_NOEUDINDIQU, XDC_DESELECTALL);
  1226.                         break;
  1227.  
  1228.                     case XDC_TOOL_MAGNET:
  1229.                         break;
  1230.  
  1231.                     case XDC_TOOL_CURVE:
  1232.                         break;
  1233.  
  1234.                     case XDC_TOOL_EXTRUDE:
  1235.                         break;
  1236.  
  1237.                     case XDC_TOOL_EDGE:
  1238.                         break;
  1239.  
  1240.                     case XDC_TOOL_GRAB:
  1241.                         {
  1242.                             BOOL bShouldDo = FALSE;
  1243.                             // Faire suivre le mouvement du curseur à tous les vertices sélectionnés
  1244.                             for (int iVertex = 0 ; iVertex <= iVertLastUsed ; iVertex++)
  1245.                             {
  1246.                                 if (bIsVertexSelected(iVertex))
  1247.                                 {
  1248.                                     Vertices[iVertex].vPoint += (Cursor1 - vVect1);
  1249.                                     bShouldDo = TRUE;
  1250.                                 }
  1251.                             }
  1252.  
  1253.                             // Recalculer tous les triangles modifiés
  1254.                             if (bShouldDo)
  1255.                                 for (int iTriangle = 0 ; iTriangle <= iTriaLastUsed ; iTriangle++)
  1256.                                     if (bIsTrianglePartiallySelected(iTriangle))
  1257.                                         bUpdateD3DTri(iTriangle);
  1258.                         }
  1259.  
  1260.                         // Faire suivre le mouvement du curseur à toutes les lampes sélectionnées
  1261.                         for (int iLamp = 0 ; iLamp <= iLampLastUsed ; iLamp++)
  1262.                         {
  1263.                             if (Lampes[iLamp].bEnabled == FALSE) continue;
  1264.                             if (Lampes[iLamp].bSelected == FALSE) continue;
  1265.  
  1266.                             Lampes[iLamp].lLamp.dvPosition += (Cursor1 - vVect1);
  1267.                             bUpdateLamp(iLamp);
  1268.                         }
  1269.  
  1270.                         // Faire suivre le mouvement du curseur à tous les objets D3D sélectionnés
  1271.                         for (int iObject = 0 ; iObject <= iObjtLastUsed ; iObject++)
  1272.                         {
  1273.                             if (Objects[iObject].bEnabled == FALSE) continue;
  1274.                             if (Objects[iObject].bSelected == FALSE) continue;
  1275.  
  1276.                             bMoveD3DObj(iObject, Cursor1 - vVect1);
  1277.                         }
  1278.  
  1279.  
  1280.                         vForce2DRefresh(XDC_MODE_COMPLET);
  1281.                         vForce3DRefresh(XDC_MODE_COMPLET);
  1282.                         goto _break;
  1283.                 }
  1284.             }
  1285.  
  1286.             // Forcer le redessin des fenêtres 2D pour prendre en compte le déplacement de l'objet
  1287.             vForce2DRefresh(XDC_MODE_PARTIEL);
  1288. _break:
  1289.             break;
  1290.  
  1291.         case WM_SIZE: //**************** T A I L L E  F E N E T R E ****************
  1292.             // Détruire et recréer le double buffer avec les nouvelles dimensions de la fenêtre
  1293.             iX = LOWORD(lParam);  // width of client area 
  1294.             iY = HIWORD(lParam); // height of client area 
  1295.             
  1296.             SelectObject(pWT -> hdcDBuf, pWT -> holdDBuf);
  1297.             DeleteObject(pWT -> hbDBuf);
  1298.  
  1299.             SelectObject(pWT -> hdcTBuf, pWT -> holdTBuf);
  1300.             DeleteObject(pWT -> hbTBuf);
  1301.             
  1302.             if (!(pWT -> hbDBuf = CreateCompatibleBitmap(hdcWin, iX, iY)))
  1303.             {
  1304.                 PostQuitMessage(0);
  1305.                 break;
  1306.             }
  1307.             
  1308.             pWT -> holdDBuf = SelectObject(pWT -> hdcDBuf, pWT -> hbDBuf);
  1309.  
  1310.             if (!(pWT -> hbTBuf = CreateCompatibleBitmap(hdcWin, iX, iY)))
  1311.             {
  1312.                 PostQuitMessage(0);
  1313.                 break;
  1314.             }
  1315.             
  1316.             pWT -> holdTBuf = SelectObject(pWT -> hdcTBuf, pWT -> hbTBuf);
  1317.  
  1318.             // Forcer le redessin complet de la fenêtre
  1319.             PostMessage(hWnd, WM_PAINT, 0, (LPARAM) TRUE);
  1320.  
  1321.             break;
  1322.  
  1323.         case WM_GETMINMAXINFO:
  1324.             // Prevent the window from going smaller than some minimum size
  1325.             ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
  1326.             ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
  1327.             break;
  1328.  
  1329.         case WM_NCLBUTTONDBLCLK :
  1330.             ShowWindow(hWnd, SW_SHOWMAXIMIZED);
  1331.             break;
  1332.  
  1333.         case WM_COMMAND:
  1334.             PostMessage(hWndMenu, uMsg, wParam, lParam );
  1335.             break;
  1336.         
  1337.         // case WM_CLOSE:    // (ne devrait jamais survenir : pas de close gadget)
  1338.         case WM_DESTROY:
  1339.             // Libérer les objets GDI
  1340.             if (hpenWhite)        { DeleteObject(hpenWhite);        hpenWhite = NULL; }
  1341.             if (hpenRed)        { DeleteObject(hpenRed);        hpenRed = NULL; }
  1342.             if (hpenYellow)        { DeleteObject(hpenYellow);        hpenYellow = NULL; }
  1343.             if (hpenCyan)        { DeleteObject(hpenCyan);        hpenCyan = NULL; }
  1344.             if (hpenPink)        { DeleteObject(hpenPink);        hpenPink = NULL; }
  1345.             if (hpenGrey)        { DeleteObject(hpenGrey);        hpenGrey = NULL; }
  1346.             if (hbrDkBlueSk)    { DeleteObject(hbrDkBlueSk);    hbrDkBlueSk = NULL; }
  1347.             if (hbrLtBlueSk)    { DeleteObject(hbrLtBlueSk);    hbrLtBlueSk = NULL; }
  1348.             if (hpenDkBlueSk)    { DeleteObject(hpenDkBlueSk);    hpenDkBlueSk = NULL; }
  1349.  
  1350.             // Détruire le double buffer
  1351.             SelectObject(pWT -> hdcDBuf, pWT -> holdDBuf);
  1352.             SelectObject(pWT -> hdcDBuf, pWT -> holdDFont);
  1353.             DeleteObject(pWT -> hbDBuf);
  1354.             DeleteDC(pWT -> hdcDBuf);
  1355.  
  1356.             // Détruire le triple buffer
  1357.             SelectObject(pWT -> hdcTBuf, pWT -> holdTBuf);
  1358.             SelectObject(pWT -> hdcTBuf, pWT -> holdTBrush);
  1359.             SelectObject(pWT -> hdcTBuf, pWT -> holdTFont);
  1360.             DeleteObject(pWT -> hbTBuf);
  1361.             DeleteDC(pWT -> hdcTBuf);
  1362.  
  1363.             // Détruire la structure de données attachée à la fenêtre
  1364.             free(pWT);
  1365.  
  1366.             // Libérer le HDC de la fenêtre
  1367.             ReleaseDC(hWnd, hdcWin);
  1368.  
  1369.             // PostQuitMessage(0);
  1370.             return 0L;
  1371.     }
  1372.     
  1373.     // Libérer le HDC de la fenêtre
  1374.     ReleaseDC(hWnd, hdcWin);
  1375.  
  1376.     return DefWindowProc( hWnd, uMsg, wParam, lParam );
  1377. }
  1378.  
  1379.